#include "hal_tm1616.h"
#include "hk32c030xx_gpio.h"
#include "systick.h"
#include "hal_tty.h"
#include "hal_motor.h"

#define DIO_H()		GPIO_SetBits(TM_SDA_PORT,TM_SDA_PIN)
#define DIO_L()		GPIO_ResetBits(TM_SDA_PORT,TM_SDA_PIN)

#define STB_H()		GPIO_SetBits(TM_STB_PORT,TM_STB_PIN)
#define STB_L()		GPIO_ResetBits(TM_STB_PORT,TM_STB_PIN)

#define CLK_H()		GPIO_SetBits(TM_SCL_PORT,TM_SCL_PIN)
#define CLK_L()		GPIO_ResetBits(TM_SCL_PORT,TM_SCL_PIN)

static uint8_t seg_fault_table[] = {
	0x00,	0x40/* - */, 0x48 /* 二 */, 0x49 /* 三 */,
};

static uint8_t seg_table[] = {
	0x3F,/*0*/ 	0x06,/*1*/	0x5B,/*2*/	0x4F,/*3*/
    0x66,/*4*/	0x6D,/*5*/	0x7D,/*6*/	0x07,/*7*/
	0x7F,/*8*/	0x6F,/*9*/	0x77,/*10 A*/	0x7C,/*11 b*/
	0x58,/*12 c*/	0x5E,/*13 d*/	0x79,/*14 E*/	0x71,/*15 F*/
	0x3D,/*16 G*/	0x76,/*17 H*/ 0x06,/*18 I*/	0x1F,/*19 J*/ 0x00,/*20 K*/
	0x38,/*21 L*/	0x15,/*22 M*/ 0x37,/*23 n*/ 0x3F,/*24 O*/ 0x73,/*25 P*/
	0x67,/*26 Q*/	0x50,/*27 r*/ 0x6D,/*28 S*/ 0x78,/*29 t*/ 0x3E,/*30 U*/
	0x1C,/*31 V*/	0x2A,/*32 W*/ 0x76,/* X*/0x6E,/*Y*/0x5B,/*Z*/
	0x00,/* 黑屏*/
};

static void tm1616_send_byte(uint8_t data) {
    
    for(int i = 0; i < 8;i++) {
        CLK_L();
        delay_us(2);
        if((data & 0x01) == 0x01)
            DIO_H();
        else
            DIO_L();
        data >>= 1;
        CLK_H();
    }
}

static void tm1616_write_cmd(uint8_t cmd) {
    
    STB_L();
    tm1616_send_byte(cmd);
    STB_H();
}

static void tm1616_write_reg(uint8_t addr,uint8_t data) {
    STB_L();
    tm1616_send_byte(TM_BASE_ADDR | addr);
    tm1616_send_byte(data);
    STB_H();
}


static void tm1616_write_seg(uint8_t addr,uint8_t data) {
    
    tm1616_write_cmd(DISPLAY_ADDR_NORMAL);
    tm1616_write_reg(addr,data);
}

static void tm1616_clear() {

    tm1616_write_cmd(DISPLAY_CTRL);
    tm1616_write_cmd(DISPLAY_ADDR_INC);
    
    STB_L();
    tm1616_send_byte(TM_BASE_ADDR);
    for(int i = 0; i < 16;i++) {
        tm1616_send_byte(0x00);
    }

    STB_H();
}

static int tm1616_show_num(uint8_t addr,uint8_t dat) {
    tm1616_write_seg(addr,seg_table[dat]);
    return 0;
}

static void tm1616_init() {
	
	GPIO_InitTypeDef tm1616_seg;
	RCC_AHBPeriphClockCmd(TM_IO_RCU, ENABLE);
	
    tm1616_seg.GPIO_Pin = TM_STB_PIN | TM_SCL_PIN | TM_SDA_PIN;
    tm1616_seg.GPIO_Mode = GPIO_Mode_OUT;
    tm1616_seg.GPIO_OType = GPIO_OType_PP;
    tm1616_seg.GPIO_Speed = GPIO_Speed_50MHz;
    tm1616_seg.GPIO_PuPd = GPIO_PuPd_NOPULL;
    tm1616_seg.GPIO_Schmit = GPIO_Schmit_Disable;
    GPIO_Init(TM_STB_PORT, &tm1616_seg);
	
	tm1616_clear();
}

static int tm1616_show_dec(uint16_t dec) {

    tm1616_write_cmd(DISPLAY_ADDR_NORMAL);
	for(int i = 3;i >= 0;i--) {
		if(dec == 0) {
			tm1616_write_reg(i * 2,seg_table[21]);
		} else {
			tm1616_write_reg(i * 2,seg_table[dec % 10]);
			dec /= 10;
		}
	}
    return 0;
}

static int tm1616_show_string(const char *data,int len) {
    
	tm1616_write_cmd(DISPLAY_ADDR_NORMAL);
	for(int i = len - 1;i >= 0;i--) {
		int idx = data[i] - 'A' + 10;
		//g_tty_.printf(" idx %d \r\n",idx);
		tm1616_write_reg(i * 2,seg_table[idx]);
	}
    return 0;
}

static int tm1616_show_hex(uint16_t hec) {

    tm1616_write_cmd(DISPLAY_ADDR_NORMAL);
	for(int i = 3;i >= 0;i--) {
		if(hec == 0) {
			tm1616_write_reg(i * 2,seg_table[21]);
		} else {
			tm1616_write_reg(i * 2,seg_table[hec % 16]);
			hec /= 16;
		}
	}

    return 0;
}

static int tm1616_change_char(int index,uint8_t c) {
	tm1616_write_cmd(DISPLAY_ADDR_NORMAL);
	int idx = 0;
	if(c > '9') {
		idx = c - 'A' + 10;
	} else {
		idx = c - '0';
	}
	
	tm1616_write_reg(index * 2,seg_table[idx]);
}

static int tm1616_show_mode(const char *data,int len) {
	
	tm1616_write_cmd(DISPLAY_ADDR_NORMAL);
	for(int i = len - 1;i >= 0;i--) {
		int idx = data[i] - 'A' + 10;
		tm1616_write_reg(i * 2,seg_table[idx]);
	}
    return 0;
}

static int tm1616_show_time(uint16_t dec) {
	
	tm1616_write_cmd(DISPLAY_ADDR_NORMAL);
	tm1616_write_reg(6,seg_table[dec % 10]);
	dec = dec / 10;
	if(dec <= 0)
		tm1616_write_reg(4,0);
	else 
		tm1616_write_reg(4,seg_table[dec % 10]);
	
	return 0;
}

static int tm1616_show_fault(uint8_t hex) {
	tm1616_write_cmd(DISPLAY_ADDR_NORMAL);

	tm1616_write_reg(2,seg_table[hex % 16]);
	tm1616_write_reg(0,seg_table[hex / 16]);
	return 0;
}

static int tm1616_show_floor(uint16_t floor,uint8_t dir) {

	tm1616_write_cmd(DISPLAY_ADDR_NORMAL);
	
	if(dir)
		tm1616_write_reg(2,seg_table[dir - 'A' + 10]);
	else 
		tm1616_write_reg(2,seg_table[0]);
	
	if(floor > 17)
		floor = 0;
	
	tm1616_write_reg(0,seg_table[floor]);
	return 0;
}

static int tm1616_show_state(uint8_t dir,uint8_t jt_s,uint8_t door,uint8_t pc_s) {
	uint8_t value = 0;
	
	if(dir == MOTOR_STATE_UP) {
		value |= 1;
	} else if(dir == MOTOR_STATE_DOWN) {
		value |= (1 << 1);
	}
	
	if(door)
		value |= (1 << 4);
	
	if(jt_s)
		value |= (1 << 6);
	
	if(pc_s)
		value |= (1 << 5);
	
	tm1616_write_cmd(DISPLAY_ADDR_NORMAL);
	tm1616_write_reg(4,value);
}

static int tm1616_slave_show(int8_t floor) {

	tm1616_write_cmd(DISPLAY_ADDR_NORMAL);
	if(floor < 0) {
		tm1616_write_reg(0,seg_fault_table[1]);
		floor = -floor;
	} else {
		tm1616_write_reg(0,0);
	}

	if(floor > 17)
		floor = 0;	
	tm1616_write_reg(2,seg_table[floor]);
}

static int tm1616_slave_fault(uint8_t fault) {
	tm1616_write_cmd(DISPLAY_ADDR_NORMAL);

	tm1616_write_reg(2,seg_table[fault % 16]);
	tm1616_write_reg(0,seg_table[fault / 16]);
}

const tm1616_t g_tm1616_ = {
    tm1616_init,
	tm1616_show_mode,
	tm1616_show_time,
	tm1616_show_fault,
	tm1616_show_floor,
	tm1616_show_state,
	tm1616_slave_show,
	tm1616_slave_fault,
};